package thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 明白 加锁意义,如何加锁
 *  不希望某个对象(或唯一资源)被多线程并行处理的并发情况,让唯一资源的相关代码变成单线程原子化
 *
 * @see normalTicket -if(number > 0){}
 * 为什么 不出现负数?
 *    >其实是会的 只是太快了读和写貌似成为了原子化操作
 *     >> 建议涉及部分 "加锁" 保证唯一一个线程(原子化),时间片用完 换其他线程也只是阻塞
 *      >>> 推出->交替输出 sout执行周期太长 读+输出 线程时间片太短 读好输出执行到一半就换线程了
 *
 * @author yuank
 * @date 2024/12/23 15:44:32
 */
class ThreeThreadTicket {
    public static void main(String[] args) {
        forTest normalTicket = new forTest();

        new Thread(() -> {
            for (int i = 0; i < 50; i++){normalTicket.sale();}
        },"a").start();

        new Thread(() -> {
            for (int i = 0; i < 50; i++){normalTicket.sale();}
        },"b").start();

        new Thread(() -> {
            for (int i = 0; i < 50; i++){normalTicket.sale();}
        },"c").start();
    }
}

class forTest{
    int number;
    public forTest() { number = 30;}

    public void sale(){
        if (number > 0){
            number--;
            synchronized (this) { // 这里明显没能理解到资源处理只能一个线程
                System.out.println("剩余票数: " + number);
            }
        }
    }
}

//不加锁
class normalTicket{
    int number;
    public normalTicket() { number = 50; }

    public void sale(){
        if (number > 0){
            number--;
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName + "；剩余票数: " + number );
        }
    }
}

//synchronized锁
class SynTicket {
    int number;
    public SynTicket() { number = 30; }

    public synchronized void sale(){
        if (number > 0){
            number--;
            System.out.println("剩余票数: " + number);
        }
    }

}

//可重入锁
class LockTicket {
    int number;
    Lock lock = new ReentrantLock();
    public LockTicket() { number = 30;}

    public void sale(){
        lock.lock();
        try{if (number > 0){
                number--;
                System.out.println("剩余票数: " + number);
            }}
        catch(Exception e) {e.printStackTrace();}
        finally {lock.unlock();}
    }
}

